﻿using System;
using System.Reflection;
using MugenInjection.Delegates;

namespace MugenInjection.Interception.Proxy
{
    /// <summary>
    /// Represents the base class for represent a method proxy metadata.
    /// </summary>
    public class MethodProxy : ProxyBase
    {
        #region Fields

        private Action _onInvoke;

        #endregion

        #region Reflection info

#if NETFX_CORE
        private static readonly Type ProxyType = typeof(MethodProxy);

        internal static PropertyInfo InputParametersProperty = ProxyType.GetProperty("InputParameters");

        internal static PropertyInfo OnInvokeProperty = ProxyType.GetProperty("OnInvoke");

        internal static PropertyInfo ReturnValueProperty = ProxyType.GetProperty("ReturnValue");

        internal static PropertyInfo MethodProperty = ProxyType.GetProperty("Method");

        internal static PropertyInfo InstanceProperty = ProxyType.GetProperty("Instance");
#else
        private const BindingFlags BindingFlagsDefault = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
        private static readonly Type ProxyType = typeof (MethodProxy);

        internal static PropertyInfo InputParametersProperty = ProxyType.GetProperty("InputParameters", BindingFlagsDefault);

        internal static PropertyInfo OnInvokeProperty = ProxyType.GetProperty("OnInvoke", BindingFlagsDefault);

        internal static PropertyInfo ReturnValueProperty = ProxyType.GetProperty("ReturnValue", BindingFlagsDefault);

        internal static PropertyInfo MethodProperty = ProxyType.GetProperty("Method", BindingFlagsDefault);

        internal static PropertyInfo InstanceProperty = ProxyType.GetProperty("Instance", BindingFlagsDefault);
#endif


        #endregion

        #region Property

        /// <summary>
        /// Gest the original action, if any.
        /// </summary>
        public override Action OriginalAction
        {
            get { return Method; }
        }

        /// <summary>
        /// Gets or sets a method for the interception.
        /// </summary>
        public override Action OnInvoke
        {
            get
            {
                if (_onInvoke == null)
                    return Method;
                return _onInvoke;
            }
            set { _onInvoke = value; }
        }

        /// <summary>
        /// Gets the input parameters of the method.
        /// </summary>
        public object[] InputParameters { get; protected internal set; }

        /// <summary>
        /// Gets the output parameter of the method.
        /// </summary>
        public object ReturnValue { get; protected internal set; }

        /// <summary>
        /// Gets the original method.
        /// </summary>
        public Action Method { get; protected internal set; }

        #endregion

        #region Implementation of ProxyBase

        /// <summary>
        /// Creates a new instance of <see cref="ProxyBase"/>.
        /// </summary>
        /// <returns>An instance of <see cref="ProxyBase"/>.</returns>
        public override ProxyBase Create()
        {
            return new MethodProxy();
        }

        #endregion
    }
}